<template>
  <transition>
    <div class="calcMain" v-if="state.visible" ref="calc" :style="{ top: state.initTop, left: state.initLeft }">
      <div class="title" @pointerdown="drag"
        ><span>计算器</span><el-icon class="close-btn" @click="closeCalc"><Close /></el-icon
      ></div>
      <div class="calc">
        <div class="result" :style="{ gridArea: 'result', fontSize: state.equationSize + 'px' }">{{ state.equation }}</div>
        <div class="btn" style="grid-area: ac" @click="clear">{{ state.equation !== '0' ? 'C' : 'AC' }}</div>
        <div class="btn" style="grid-area: plus-minus" @click="calculateToggle">±</div>
        <div class="btn" style="grid-area: percent" @click="calculatePercentTage">%</div>
        <div class="btn" style="grid-area: divide" @click="append('÷')">÷</div>
        <div class="btn" style="grid-area: multiply" @click="append('×')">×</div>
        <div class="btn" style="grid-area: subtract" @click="append('-')">-</div>
        <div class="btn" style="grid-area: add" @click="append('+')">+</div>
        <div class="btn" style="grid-area: equal" @click="calculate">=</div>

        <div class="btn" style="grid-area: number-1" @click="append(1)">1</div>
        <div class="btn" style="grid-area: number-2" @click="append(2)">2</div>
        <div class="btn" style="grid-area: number-3" @click="append(3)">3</div>
        <div class="btn" style="grid-area: number-4" @click="append(4)">4</div>
        <div class="btn" style="grid-area: number-5" @click="append(5)">5</div>
        <div class="btn" style="grid-area: number-6" @click="append(6)">6</div>
        <div class="btn" style="grid-area: number-7" @click="append(7)">7</div>
        <div class="btn" style="grid-area: number-8" @click="append(8)">8</div>
        <div class="btn" style="grid-area: number-9" @click="append(9)">9</div>
        <div class="btn" style="grid-area: number-0" @click="append(0)">0</div>

        <div class="btn" style="grid-area: dot" @click="append('.')">.</div>
      </div>
    </div>
  </transition>
</template>
<script setup>
  import { ref, reactive, watch } from 'vue'
  defineOptions({ name: 'v-calc' })
  const props = defineProps({
    visible: {
      type: Boolean,
      default: true,
    },
  })
  // 初始化数据
  let calc = ref(null)
  let state = reactive({
    initLeft: '50px', // 计算器距离浏览器左边的距离
    initTop: '50px', // 计算器距浏览器顶部的距离
    visible: false, // 计算机开启状态
    equationSize: 20, // 计算结果的字体大小
    equation: '0', // 显示计算结果， 初始为0
    isDecimalAdded: false, // 判断是否已经输入小数位
    isOperatorAdded: false, // 判断是否已点击加、减、乘、除
    isStarted: false, // 判断计算器是否已开始输入数字
  })
  // 函数方法
  const emit = defineEmits('closeCalculator')
  // 用来判断 character 是否加减乘除的符号存在
  const isOperator = (character) => {
    return ['+', '-', '×', '÷'].indexOf(character) > -1
  }
  // 点击加减乘除或小数位时
  const append = (character) => {
    // 首先判断equation不等于0，并且不是运算符号时
    if (state.equation === '0' && !isOperator(character)) {
      // 判断是数字还是小数点
      if (character === '.') {
        state.equation += '' + character
        state.isDecimalAdded = true
      } else {
        state.equation = '' + character
      }
      state.isStarted = true
      return
    }

    // 输入数字的时候
    if (!isOperator(character)) {
      if (character === '.' && state.isDecimalAdded) {
        return
      }
      if (character === '.') {
        state.isDecimalAdded = true
        state.isOperatorAdded = true
      } else {
        state.isOperatorAdded = false
      }
      state.equation += '' + character
    }

    // 判断当前是否运算符号
    if (isOperator(character) && !state.isOperatorAdded) {
      state.equation += '' + character
      state.isDecimalAdded = false
      state.isOperatorAdded = true
    }
  }
  // 点击等号
  const calculate = () => {
    let result = state.equation.replace(new RegExp('×', 'g'), '*').replace(new RegExp('÷', 'g'), '/')
    state.equation = parseFloat(eval(result).toFixed(9)).toString()
    state.isDecimalAdded = false
    state.isOperatorAdded = false
  }
  // 点击±号
  const calculateToggle = () => {
    if (state.isOperatorAdded || !state.isStarted) {
      return
    }
    state.equation = state.equation + '* -1'
    calculate()
  }
  // 点击%号
  const calculatePercentTage = () => {
    if (state.isOperatorAdded || !state.isStarted) {
      return
    }
    state.equation = state.equation + '* 0.01'
    calculate()
  }
  // 点击AC
  const clear = () => {
    state.equation = '0'
    state.isDecimalAdded = false
    state.isOperatorAdded = false
    state.isStarted = false
  }
  // 拖拽
  const drag = function (e) {
    var eve = e || window.event
    var pointerId = e.pointerId
    const dragbar = e.target
    const CtlEl = calc.value
    if (typeof dragbar.setPointerCapture != 'undefined') {
      //SetCapture捕捉鼠标到指定的元素
      //dragAry.setCapture();
      dragbar.setPointerCapture(pointerId)
    }
    CtlEl.style.zIndex = 999999 //当前拖拽的在最前面显示
    const mx = eve.clientX //鼠标点击时的坐标
    const my = eve.clientY //鼠标点击时的坐标
    const dleft = CtlEl.offsetLeft //窗口初始位置
    const dtop = CtlEl.offsetTop
    const clientWidth = document.documentElement.clientWidth //页面的宽
    const oWidth = CtlEl.offsetWidth //窗口的宽
    const maxX = clientWidth - oWidth // x轴能移动的最大距离
    const clientHeight = document.documentElement.clientHeight //页面的高
    const oHeight = CtlEl.offsetHeight //窗口的高度
    const maxY = clientHeight - oHeight //y轴能移动的最大距离

    document.onmousemove = function (e) {
      const x = e.clientX
      const y = e.clientY
      let left = x - mx + dleft //移动后的新位置
      let top = y - my + dtop //移动后的新位置
      if (left < 0) left = 0
      if (left > maxX) left = maxX
      if (top < 0) top = 0
      if (top > maxY) top = maxY

      state.initLeft = left + 'px'
      state.initTop = top + 'px'
    }
    document.onmouseup = function (e) {
      //当鼠标弹起来的时候不再移动
      document.onmousemove = null
      document.onmouseup = null //预防鼠标弹起来后还会循环（即预防鼠标放上去的时候还会移动）
      if (typeof dragbar.releasePointerCapture != 'undefined') {
        dragbar.releasePointerCapture(pointerId)
      }
    }
  }
  // 关闭计算机
  const closeCalc = () => {
    state.visible = false
    state.equation = '0'
    emit('closeCalculator', false)
  }
  // 监听
  watch(
    [() => state.equation, () => props.visible],
    () => {
      state.visible = props.visible
      if (state.equation.length >= 20) {
        if (state.equation.length >= 28) {
          state.equationSize = 12
        } else {
          state.equationSize = 20 - (state.equation.length - 20)
        }
      } else {
        state.equationSize = 20
      }
    },
    { immediate: true, deep: true }
  )
</script>
<style scoped rel="stylesheet/scss" lang="scss">
  .calcMain {
    --button-width: 60px;
    --button-height: 60px;
    --white: #fff;
    --black: #333;

    position: fixed;
    //right: 30px;
    //bottom: 30px;
    z-index: 999999;

    background-color: var(--black);
    box-shadow:
      0 0 2px rgb(255 234 0),
      0 0 5px rgb(21 115 228);
    border-radius: 4px;
    color: var(--white);
    font-family: sans-serif;
    overflow: hidden;
    .title {
      background-color: #409eff;
      color: #fff;
      display: flex;
      align-items: center;
      cursor: move;
      padding: 5px 10px;
      font-size: 14px;
      span {
        flex: 1;
      }
      .close-btn {
        //position: absolute;
        //top: -12px;
        //right: -12px;
        //background-color: #343434;
        border-radius: 50%;
        cursor: pointer;
        padding: 1px;
        font-size: 24px;
        //box-shadow: 0 0 5px rgb(255 234 0), 0 0px 12px rgb(21 115 228);
      }
    }
    .calc {
      //width: 500px;
      //height: 300px;
      padding: 10px;
      display: grid;
      grid-template-areas:
        'result result result result'
        'ac plus-minus percent divide'
        'number-7 number-8 number-9  multiply'
        'number-4 number-5 number-6  subtract'
        'number-1 number-2 number-3  add'
        'number-0 number-0 dot  equal';
      grid-template-columns: repeat(4, var(--button-width));
      grid-template-rows: repeat(6, var(--button-height));
      .result {
        width: 100%;
        border: 1px solid var(--white);
        color: var(--white);
        //background-color: var(--white);
        padding: 5px;
        line-height: calc(var(--button-height) - 20px);
        margin-bottom: 10px;
        text-align: right;
        border-radius: 4px;
        grid-area: result;
        overflow: hidden;
        //direction: rtl;
        cursor: context-menu;
      }
      .btn {
        margin: 5px;
        padding: 0;
        border: 0;
        border-radius: calc(var(--button-height) / 2);
        font-size: 16px;
        line-height: calc(var(--button-height) - 10px);
        cursor: pointer;
        text-align: center;
        color: var(--black);
        background: linear-gradient(135deg, rgb(215 233 255) 0%, rgb(246, 246, 246) 70%);
        box-shadow:
          -4px -4px 10px -8px rgba(255, 255, 255, 1),
          4px 4px 10px -8px rgba(0, 0, 0, 0.3);
        font-weight: 600;
        &:active {
          box-shadow:
            -4px -4px 10px -8px rgba(255, 255, 255, 1) inset,
            4px 4px 10px -8px rgba(0, 0, 0, 0.3) inset;
        }
      }
    }
  }
</style>
